package com.lzx.mumianaicodegenerator.core;

import cn.hutool.json.JSONUtil;
import com.lzx.mumianaicodegenerator.ai.AiCodeGeneratorService;
import com.lzx.mumianaicodegenerator.ai.AiCodeGeneratorServiceFactory;
import com.lzx.mumianaicodegenerator.ai.model.enums.CodeGenTypeEnum;
import com.lzx.mumianaicodegenerator.ai.model.HtmlCodeResult;
import com.lzx.mumianaicodegenerator.ai.model.MultiFileCodeResult;
import com.lzx.mumianaicodegenerator.ai.model.message.AiResponseMessage;
import com.lzx.mumianaicodegenerator.ai.model.message.ToolExecutedMessage;
import com.lzx.mumianaicodegenerator.ai.model.message.ToolRequestMessage;
import com.lzx.mumianaicodegenerator.constant.AppConstant;
import com.lzx.mumianaicodegenerator.core.builder.VueProjectBuilder;
import com.lzx.mumianaicodegenerator.core.parser.CodeParserExecutor;
import com.lzx.mumianaicodegenerator.core.saver.CodeFileSaverExecutor;
import com.lzx.mumianaicodegenerator.exception.BusinessException;
import com.lzx.mumianaicodegenerator.exception.ErrorCode;
import com.lzx.mumianaicodegenerator.model.enums.GenTypeEnum;
import com.lzx.mumianaicodegenerator.service.AiGenerationInterruptService;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.service.TokenStream;
import dev.langchain4j.service.tool.ToolExecution;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import reactor.core.Disposable;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.io.File;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

@Service
@Slf4j
public class AiCodeGeneratorFacade {
    
    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;
    @Resource
    private AiGenerationInterruptService aiGenerationInterruptService;
    @Resource
    private VueProjectBuilder vueProjectBuilder;

//    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenTypeEnum) {
//        if (codeGenTypeEnum == null) {
//            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"生成类型为空");
//        }
//        return switch (codeGenTypeEnum) {
//            case HTML -> generateAndSaveHtmlCode(userMessage);
//            case MULTI_FILE -> generateAndSaveMultiFileCode(userMessage);
//            default -> {
//                String errorMessage = "不支持的生成类型: " + codeGenTypeEnum.getValue();
//                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
//            }
//        };
//    }


//    private File generateAndSaveHtmlCode(String userMessage) {
//        HtmlCodeResult result = aiCodeGeneratorService.generateHtmlCode(userMessage);
//        return CodeFileSaver.saveHtmlCodeResult(result);
//    }
//    private File generateAndSaveMultiFileCode(String userMessage) {
//        MultiFileCodeResult result = aiCodeGeneratorService.generateMultiFileCode(userMessage);
//        return CodeFileSaver.saveMultiFileCodeResult(result);
//    }
//    private Flux<String> generateAndSaveHtmlCodeStream(String userMessage) {
//        Flux<String> result = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
//        StringBuilder codeBuilder = new StringBuilder();
//        return result
//                .doOnNext(chunk -> codeBuilder.append(chunk))
//                .doOnComplete(() -> {
//                    try {
//                        String completeHtmlCode = codeBuilder.toString();
//                        HtmlCodeResult htmlCodeResult = CodeParser.parseHtmlCode(completeHtmlCode);
//                        File savedDir = CodeFileSaver.saveHtmlCodeResult(htmlCodeResult);
//                        log.info("HTML代码保存成功: {}", savedDir.getAbsolutePath());
//                    } catch (Exception e) {
//                        log.error("HTML代码保存失败", e);
//                    }
//
//        });
//    }
//    private Flux<String> generateAndSaveMultiFileCodeStream(String userMessage) {
//        Flux<String> result = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
//        StringBuilder codeBuilder = new StringBuilder();
//        return result
//                .doOnNext(chunk -> codeBuilder.append(chunk))
//                .doOnComplete(() -> {
//                   try {
//                       String completeMultiFileCode = codeBuilder.toString();
//                       MultiFileCodeResult multiFileCodeResult = CodeParser.parseMultiFileCode(completeMultiFileCode);
//                       File savedDir = CodeFileSaver.saveMultiFileCodeResult(multiFileCodeResult);
//                       log.info("多文件代码保存成功: {}", savedDir.getAbsolutePath());
//                   } catch (Exception e) {
//                       log.error("多文件代码保存失败", e);
//                   }
//                });
//    }


    /**
     * 统一入口：根据类型生成并保存代码
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     * @return 保存的目录
     */
    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenTypeEnum,Long appId) {
        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId,codeGenTypeEnum);
        return switch (codeGenTypeEnum) {
            case HTML -> {
                HtmlCodeResult result = aiCodeGeneratorService.generateHtmlCode(userMessage);
                yield CodeFileSaverExecutor.executeSaver(result, CodeGenTypeEnum.HTML,appId);
            }
            case MULTI_FILE -> {
                MultiFileCodeResult result = aiCodeGeneratorService.generateMultiFileCode(userMessage);
                yield CodeFileSaverExecutor.executeSaver(result, CodeGenTypeEnum.MULTI_FILE,appId);
            }

            default -> {
                String errorMessage = "不支持的生成类型：" + codeGenTypeEnum.getValue();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, errorMessage);
            }
        };
    }

    /**
     * 统一入口：根据类型生成并保存代码（流式）
     *
     * @param userMessage     用户提示词
     * @param codeGenTypeEnum 生成类型
     */
    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenTypeEnum, Long appId, Integer genType) {
        GenTypeEnum genTypeEnum = GenTypeEnum.getEnumByValue(genType);
        if (genTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "选择类型不存在");
        }

        if (codeGenTypeEnum == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成类型为空");
        }
        
        // 清除之前的中断标志，开始新的生成
        aiGenerationInterruptService.clearInterrupt(appId);
        
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId, codeGenTypeEnum);
        
        if (genTypeEnum == GenTypeEnum.TALK) {
            return aiCodeGeneratorService.talkAndNotChange(appId, userMessage)
                .takeWhile(chunk -> !aiGenerationInterruptService.isInterrupted(appId))
                .doOnComplete(() -> aiGenerationInterruptService.clearInterrupt(appId))
                .doOnError(error -> aiGenerationInterruptService.clearInterrupt(appId))
                .doOnCancel(() -> {
                    log.info("应用 {} 的对话生成被取消", appId);
                    aiGenerationInterruptService.clearInterrupt(appId);
                });
        }
        
        if (genTypeEnum == GenTypeEnum.CHANGE && codeGenTypeEnum == CodeGenTypeEnum.VUE_PROJECT) {
            TokenStream tokenStream = aiCodeGeneratorService.changeVueProjectCodeStream(appId, userMessage);
            return processTokenStreamWithInterrupt(tokenStream, appId);
        }
        
        return switch (codeGenTypeEnum) {
            case HTML -> {
                Flux<String> codeStream = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
                yield processCodeStreamWithInterrupt(codeStream, CodeGenTypeEnum.HTML, appId);
            }
            case MULTI_FILE -> {
                Flux<String> codeStream = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                yield processCodeStreamWithInterrupt(codeStream, CodeGenTypeEnum.MULTI_FILE, appId);
            }
            case VUE_PROJECT -> {
                TokenStream tokenStream = aiCodeGeneratorService.generateVueProjectCodeStream(appId, userMessage);
                yield processTokenStreamWithInterrupt(tokenStream, appId);
            }
        };
    }
    
    /**
     * 处理代码流并支持中断
     */
    private Flux<String> processCodeStreamWithInterrupt(Flux<String> codeStream, CodeGenTypeEnum codeGenType, Long appId) {
        return codeStream
            .takeWhile(chunk -> !aiGenerationInterruptService.isInterrupted(appId))
            .doOnNext(chunk -> {
                // 每次输出时检查中断状态
                if (aiGenerationInterruptService.isInterrupted(appId)) {
                    log.info("检测到应用 {} 的生成被中断", appId);
                }
            })
            .doOnComplete(() -> {
                if (!aiGenerationInterruptService.isInterrupted(appId)) {
                    // 正常完成时保存代码
                    // 这里可以添加保存逻辑
                }
                aiGenerationInterruptService.clearInterrupt(appId);
            })
            .doOnError(error -> {
                log.error("应用 {} 代码生成出错: {}", appId, error.getMessage());
                aiGenerationInterruptService.clearInterrupt(appId);
            })
            .doOnCancel(() -> {
                log.info("应用 {} 的代码生成被取消", appId);
                aiGenerationInterruptService.clearInterrupt(appId);
            });
    }
    
    /**
     * 处理TokenStream并支持中断
     */
    private Flux<String> processTokenStreamWithInterrupt(TokenStream tokenStream, Long appId) {
        AtomicReference<Disposable> interruptChecker = new AtomicReference<>();
        AtomicBoolean streamCompleted = new AtomicBoolean(false);
        AtomicBoolean userInterrupted = new AtomicBoolean(false);
        
        return Flux.<String>create(sink -> {
            // 激进的中断检查（每50ms）
            Disposable interrupt = Schedulers.parallel().schedulePeriodically(
                () -> {
                    if (aiGenerationInterruptService.isInterrupted(appId) && !streamCompleted.get()) {
                        log.warn("用户中断检测：立即终止应用 {} 的AI生成流", appId);
                        userInterrupted.set(true);
                        streamCompleted.set(true);
                        
                        // 立即发送中断确认消息
                        try {
                            sink.next("{\"type\":\"system\",\"message\":\"✅ AI生成已停止\",\"timestamp\":" + System.currentTimeMillis() + "}");
                        } catch (Exception e) {
                            log.debug("发送中断消息时出错: {}", e.getMessage());
                        }
                        
                        // 强制完成流
                        sink.complete();
                    }
                }
                ,
                0, // 立即开始
                50, // 每50ms检查一次
                TimeUnit.MILLISECONDS
            );
            interruptChecker.set(interrupt);
            
            tokenStream.onPartialResponse((String partialResponse) -> {
                        // 优先检查用户中断
                        if (userInterrupted.get() || streamCompleted.get()) {
                            log.debug("响应被中断，忽略部分响应");
                            return;
                        }
                        
                        // 双重检查中断状态
                        if (aiGenerationInterruptService.isInterrupted(appId)) {
                            log.info("在处理响应时检测到中断标志");
                            userInterrupted.set(true);
                            streamCompleted.set(true);
                            sink.complete();
                            return;
                        }
                        
                        AiResponseMessage aiResponseMessage = new AiResponseMessage(partialResponse);
                        sink.next(JSONUtil.toJsonStr(aiResponseMessage));
                    })
                    .onPartialToolExecutionRequest((index, toolExecutionRequest) -> {
                        if (userInterrupted.get() || aiGenerationInterruptService.isInterrupted(appId)) {
                            log.debug("工具执行请求被中断");
                            sink.complete();
                            return;
                        }
                        ToolRequestMessage toolRequestMessage = new ToolRequestMessage(toolExecutionRequest);
                        sink.next(JSONUtil.toJsonStr(toolRequestMessage));
                    })
                    .onToolExecuted((ToolExecution toolExecution) -> {
                        if (userInterrupted.get() || aiGenerationInterruptService.isInterrupted(appId)) {
                            log.debug("工具执行结果被中断");
                            sink.complete();
                            return;
                        }
                        ToolExecutedMessage toolExecutedMessage = new ToolExecutedMessage(toolExecution);
                        sink.next(JSONUtil.toJsonStr(toolExecutedMessage));
                    })
                    .onCompleteResponse((ChatResponse response) -> {
                        streamCompleted.set(true);
                        
                        // 清理定时器
                        Disposable checker = interruptChecker.get();
                        if (checker != null && !checker.isDisposed()) {
                            checker.dispose();
                        }
                        
                        if (!userInterrupted.get()) {
                            log.info("AI生成正常完成，应用ID: {}", appId);
                            // 只有在未被中断时才执行后续处理
                            String projectPath = AppConstant.CODE_OUTPUT_ROOT_DIR + File.separator + "vue_project_" + appId;
                            // 构建逻辑...
                        } else {
                            log.info("AI生成被用户中断，跳过后续处理，应用ID: {}", appId);
                        }
                        
                        aiGenerationInterruptService.clearInterrupt(appId);
                        sink.complete();
                    })
                    .onError((Throwable error) -> {
                        streamCompleted.set(true);
                        
                        // 清理定时器
                        Disposable checker = interruptChecker.get();
                        if (checker != null && !checker.isDisposed()) {
                            checker.dispose();
                        }
                        
                        log.error("应用 {} TokenStream处理出错: {}", appId, error.getMessage());
                        aiGenerationInterruptService.clearInterrupt(appId);
                        
                        if (!userInterrupted.get()) {
                            sink.error(error);
                        } else {
                            // 如果是用户中断导致的错误，正常完成
                            sink.complete();
                        }
                    })
                    .start();
            })
            .timeout(Duration.ofMinutes(2)) // 缩短超时时间
            .doOnCancel(() -> {
                log.info("Flux流被取消，应用ID: {}", appId);
                streamCompleted.set(true);
                userInterrupted.set(true);
                
                // 清理资源
                Disposable checker = interruptChecker.get();
                if (checker != null && !checker.isDisposed()) {
                    checker.dispose();
                }
                aiGenerationInterruptService.clearInterrupt(appId);
            })
            .doOnComplete(() -> {
                log.info("AI生成流完成，应用ID: {}", appId);
            });
    }
    
    private Flux<String> processCodeStream(Flux<String> codeStream, CodeGenTypeEnum codeGenType,Long appId) {
        StringBuilder codeBuilder = new StringBuilder();
        return codeStream.doOnNext(chunk -> codeBuilder.append(chunk))
                .doOnComplete(() -> {
                    try {
                        String completeCode = codeBuilder.toString();
                        Object codeResult = CodeParserExecutor.executeParser(completeCode, codeGenType);
                        File savedDir = CodeFileSaverExecutor.executeSaver(codeResult, codeGenType,appId);
                        log.info("代码保存成功: {}", savedDir.getAbsolutePath());
                    } catch (Exception e) {
                        log.error("代码保存失败", e);
                    }
                });
    }



}

